package main

import (
	"errors"
	"fmt"
	"net/http"
	"os"
	"io"
)

func foo(a, b int) (i int, err error) {
	defer fmt.Printf("first defer err %v\n", err)
	defer func(err error) { fmt.Printf("second defer err %v\n", err) }(err)
	defer func() { fmt.Printf("third defer err %v\n", err) }()
	if b == 0 {
		err = errors.New("divided by zero")
		return
	}

	i = a / b
	return
}

func foo2() (i int) {

	i = 0
	defer func() {
		fmt.Println(i)
	}()

	return 2
}

func test() {
	var run func() = nil
	defer run()
	fmt.Println("runs")
}

func do() error {
	res, err := http.Get("http://www.baidu.com")
	if res != nil {
		defer res.Body.Close()
	}
	if err != nil {
		fmt.Println(err)
		return err
	}

	// ..code...

	return nil
}

func do2() (error) {
	f, err := os.Open("book.txt")
	if err != nil {
		fmt.Println("err:", err)
		return err
	}

	if f != nil {
        defer func(f io.Closer) {
            if err := f.Close(); err != nil {
                fmt.Printf("defer close book.txt err %v\n", err)
            }
        }(f)
    }

    // ..code...

    f, err = os.Open("another-book.txt")
    if err != nil {
        return err
    }
    if f != nil {
        defer func(f io.Closer) {
            if err := f.Close(); err != nil {
                fmt.Printf("defer close another-book.txt err %v\n", err)
            }
        }(f)
    }

	return nil
}

func main() {
	// foo(2, 0)
	// foo2()

	// defer func() {
	//     if err := recover(); err != nil {
	//         fmt.Println(err)
	//     }
	// }()
	// test()

	// do()
	do2()
}
